﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;

//using System.Linq;
//using System.ComponentModel;
//using System.Data;

using Emgu.CV;

using AForge;
using AForge.Imaging;
using AForge.Imaging.Filters;

namespace CokAracliKontrol
{
    public partial class ColorRangeForm : Form
    {
        Capture _capture;
        public MainForm callerForm;
        public ComboBox cbCaller;
        //public TextBox tbCaller;
        public Bitmap img;

        private bool IsBlobFiltered = false;
        private bool IsFilter = false;
        ColorFiltering colorFilter = new ColorFiltering();
        GrayscaleBT709 grayFilter = new GrayscaleBT709();
        BlobCounter blobCounter = new BlobCounter();

        public ColorRangeForm()
        {
            InitializeComponent();
        }

        private void ColorRangeForm_Load(object sender, EventArgs e)
        {
            if (cbCaller != null)
            {
                this.Text = "( Vehicle Pattern ) Color Range Selection";
            }
            else
            {
                this.Text = "( Obstacle Detector ) Color Range Selection";
            }

            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
            timer1.Enabled = true;
            _capture = callerForm._capture;

            
            nudBlobMinHeight.Value = 5;
            nudBlobMinWidth.Value = 5;
            nudColorSelectRadius.Value = 70;

            lblMinHeight.Text = nudBlobMinHeight.Value.ToString();
            lblMinWidth.Text = nudBlobMinWidth.Value.ToString();
        }

        private void ParseColorRanges(string s, IntRange redRange, IntRange greenRange, IntRange blueRange)
        {
            string sred, sblue, sgreen;
            string[] parts;
            parts = s.Split('|');


            sred = parts[0];
            sgreen = parts[1];
            sblue = parts[2];


            parts = sred.Split('-');
            redRange.Min = Convert.ToInt32(parts[0]);
            redRange.Max = Convert.ToInt32(parts[1]);


            parts = sgreen.Split('-');
            greenRange.Min = Convert.ToInt32(parts[0]);
            greenRange.Max = Convert.ToInt32(parts[1]);


            parts = sblue.Split('-');
            blueRange.Min = Convert.ToInt32(parts[0]);
            blueRange.Max = Convert.ToInt32(parts[1]);
        }


        private void timer1_Tick(object sender, EventArgs e)
        {
            if (callerForm.timerMoveAgents.Enabled)
            {
                img = callerForm.motherImage.Bitmap;
            }
            else
            {
                img = _capture.QueryFrame().Bitmap;
            }

            if (img != null)
            {
                IntRange redRange = new IntRange(hScrollBarRedMin.Value, hScrollBarRedMax.Value);
                IntRange greenRange = new IntRange(hScrollBarGreenMin.Value, hScrollBarGreenMax.Value);
                IntRange blueRange = new IntRange(hScrollBarBlueMin.Value, hScrollBarBlueMax.Value);

                ColorFiltering filter = new ColorFiltering(
                    redRange,
                    greenRange,
                    blueRange);

                filter.ApplyInPlace(img);

                string color;
                color = hScrollBarRedMin.Value.ToString() + "-" + hScrollBarRedMax.Value.ToString() + "|";
                color += hScrollBarGreenMin.Value.ToString() + "-" + hScrollBarGreenMax.Value.ToString() + "|";
                color += hScrollBarBlueMin.Value.ToString() + "-" + hScrollBarBlueMax.Value.ToString();
                textBox1.Text = color;

                int r = (redRange.Min + redRange.Max) / 2;
                int g = (greenRange.Min + greenRange.Max) / 2;
                int b = (blueRange.Min + blueRange.Max) / 2;

                textBox1.ForeColor = Color.FromArgb(255 - r, 255 - g, 255 - b);
                textBox1.BackColor = Color.FromArgb(r, g, b);

                pictureBox1.Image = img;

                if (IsBlobFiltered)
                {
                    BitmapData objectData = img.LockBits(
                    new Rectangle(0, 0, img.Width, img.Height),
                    ImageLockMode.ReadOnly, img.PixelFormat);

                    /*
                     * grayscaling 
                     */
                    UnmanagedImage grayImage = grayFilter.Apply(new UnmanagedImage(objectData));

                    /* 
                     * unlock image 
                     */
                    img.UnlockBits(objectData);

                    /*
                     * locate blobs 
                     */
                    blobCounter.ProcessImage(grayImage);
                    Rectangle[] rects = blobCounter.GetObjectsRectangles();
                    Rectangle vehicleArea;
                    int x, y;

                    if (rects.Length > 0)
                    {
                        vehicleArea = rects[0];

                        /*
                         * get object's center coordinates relative to image center 
                         */
                        int centerX, centerY;
                        centerX = (vehicleArea.Left + vehicleArea.Right) / 2;
                        centerY = (vehicleArea.Top + vehicleArea.Bottom) / 2;

                        x = centerX / (grayImage.Width / PathFinding.Pathfinder.gridSizeX);
                        y = centerY / (grayImage.Height / PathFinding.Pathfinder.gridSizeY);

                        this.Text = x.ToString() + "," + y.ToString() + " Total: " + blobCounter.ObjectsCount.ToString();
                    }
                    else
                    {
                        this.Text = "No blobs are detected !";
                    }
                }

                if (IsFilter)
                {
                    //int colpix = img.Width / PathFinding.Pathfinder.gridSizeX; // 20
                    GaussianBlur imgGaussianBlur = new GaussianBlur(1,1); // 10 - 20
                    imgGaussianBlur.ApplyInPlace(img);

                    Dilatation dilFilter = new Dilatation();
                    dilFilter.ApplyInPlace(img);
                }
            }
        }

        private void ColorRangeForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            timer1.Enabled = false;
            if (callerForm.obstacleColor != null)
            {
                
                if (img != null)
                {
                    if (cbSaveImage.Checked == true)
                    {
                        string obsFile = "obs_cf_" + DateTime.Now.ToString("ddMMyyyy'_'HHmmss") + ".jpg";
                        img.Save(obsFile);
                    }
                    
                    //img.Dispose();
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string color;
            color = hScrollBarRedMin.Value.ToString() + "-" + hScrollBarRedMax.Value.ToString() + "|";
            color += hScrollBarGreenMin.Value.ToString() + "-" + hScrollBarGreenMax.Value.ToString() + "|";
            color += hScrollBarBlueMin.Value.ToString() + "-" + hScrollBarBlueMax.Value.ToString();

            if (cbCaller != null)
            {
                cbCaller.Items.Add(color);
                cbCaller.SelectedIndex = cbCaller.Items.Count - 1;
            }
            else if (callerForm.obstacleColor != null)
            {
                callerForm.obstacleColor = color;
            }

            button2_Click(null, null);
        }

        private void nudBlobMinWidth_Scroll(object sender, ScrollEventArgs e)
        {
            lblMinWidth.Text = nudBlobMinWidth.Value.ToString();
            callerForm.minBlobWidth = Convert.ToInt32(nudBlobMinWidth.Value);
        }

        private void nudBlobMinHeight_Scroll(object sender, ScrollEventArgs e)
        {
            lblMinHeight.Text = nudBlobMinHeight.Value.ToString();
            callerForm.minBlobHeight = Convert.ToInt32(nudBlobMinHeight.Value);
        }

        void PictureBox1MouseClick(object sender, MouseEventArgs e)
        {
            Color clr = img.GetPixel(e.X, e.Y);

            int radius = Convert.ToInt32(nudColorSelectRadius.Value);
            int minred, maxred;
            int mingreen, maxgreen;
            int minblue, maxblue;

            minred = clr.R - radius;
            if (minred < 0) minred = 0;
            maxred = clr.R + radius;
            if (maxred > 255) maxred = 255;

            mingreen = clr.G - radius;
            if (mingreen < 0) mingreen = 0;
            maxgreen = clr.G + radius;
            if (maxgreen > 255) maxgreen = 255;

            minblue = clr.B - radius;
            if (minblue < 0) minblue = 0;
            maxblue = clr.B + radius;
            if (maxblue > 255) maxblue = 255;

            hScrollBarRedMin.Value = minred;
            hScrollBarRedMax.Value = maxred;

            hScrollBarGreenMin.Value = mingreen;
            hScrollBarGreenMax.Value = maxgreen;

            hScrollBarBlueMin.Value = minblue;
            hScrollBarBlueMax.Value = maxblue;
        }

        private void btnFindBlobs_Click(object sender, EventArgs e)
        {
            blobCounter.MinWidth = Convert.ToInt32(lblMinWidth.Text);
            blobCounter.MinHeight = Convert.ToInt32(lblMinHeight.Text);
            blobCounter.FilterBlobs = true;
            blobCounter.ObjectsOrder = ObjectsOrder.Size;

            IsBlobFiltered = true;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            hScrollBarRedMin.Value = 0;
            hScrollBarRedMax.Value = 255;
            hScrollBarGreenMin.Value = 0;
            hScrollBarGreenMax.Value = 255;
            hScrollBarBlueMin.Value = 0;
            hScrollBarBlueMax.Value = 255;
        }

        private void btnFilter_Click(object sender, EventArgs e)
        {
            IsFilter = !IsFilter;
        }
    }
}